﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Drawing.Imaging;

namespace WQLinkUpHelper
{
    public partial class Form1 : Form
    {
        public int oriX = 264-236, oriY = 313-100;//SIZE=35
        public int cellSize = 35;
        public int cellCntX = 16, cellCntY = 9;
        private Bitmap BigMapBmp;
        private int[,] mapArray = new int[16, 9];
        private bool isArrayGenarated = false; //数组是否已产生。
        private String MapFileName = @"E:\WQLinkUp\201277114155.bmp";
        private String workingPath= @"E:\WQLinkUp\";
        private int LastX1 = -1, LastY1 = -1;
        private int LastX2 = -1, LastY2 = -1;
        public Form1()
        {

            InitializeComponent();

            //以下是画图画线画字
            
            //BigMapBmp = new Bitmap(MapFileName); //example1.bmp//201274204700.jpg

            //Bitmap bmp = new Bitmap(MapFileName);
            //pbMain.BackgroundImage = bmp;
            //Graphics g = Graphics.FromImage(bmp); //从bmp生成graphics
            //Font font = new Font("宋体", 20);
            //g.DrawString("hello ray man", font, Brushes.Red, 0, 0);
            //for (int i = 0; i < 9; i++)
            //{
            //    g.DrawLine(Pens.Red, new Point(oriX, oriY + i * 35), new Point(oriX + 16 * 35, oriY + i * 35));//画辅助线和文字
            //    g.DrawString(i.ToString(), font, Brushes.Black, oriX - 20, oriY + i * 35);
            //}
            //for (int j = 0; j < 16; j++)
            //{
            //    g.DrawLine(Pens.Red, new Point(oriX + j * 35, oriY), new Point(oriX + j * 35, oriY + 9 * 35));
            //    g.DrawString(j.ToString(), font, Brushes.Black, oriX + j * 35, oriY - 20);
            //}

            //g.Dispose();
            //pbMain.Size = new Size(1024, 768);
           
            
        }
        public String copareWith(int cellX,int cellY)
        {
            String res = "";
            res = cellX + "," + cellY + "\r\n";

            int[] source = calcTrait(cellX, cellY, BigMapBmp);
            for (int x = 0; x < cellCntX; x++)
            {
                for (int y = 0; y < cellCntY; y++)
                {
                    if (x == cellX && y == cellY) continue;
                    int[] newComer = calcTrait(x, y, BigMapBmp);
                    if (compareTraits(source, newComer))
                    {
                        res += x + "," + y + "\r\n";
                        //相似则

                    }
                }
            }
            return res;
        }
        /// <summary>
        /// 随机选一个格子，找与格子相似的格子，返回相似格子列表
        /// </summary>
        /// <returns></returns>
        public string randomCompare()
        {
            String res = "";
            int cellxx = new Random().Next(9 * 16);
            int cellX = cellxx % 16; //产生源
            int cellY = 16 / cellxx;
            res = cellX + "," + cellY+"\r\n";

            int[] source= calcTrait(cellX, cellY, BigMapBmp);
            for (int x = 0; x < cellCntX; x++)
            {
                for (int y = 0; y < cellCntY; y++)
                {
                    if (x == cellX && y == cellY) continue;
                    int[] newComer= calcTrait(x, y, BigMapBmp);
                    if (compareTraits(source, newComer))
                    {
                        res += x + "," + y + "\r\n";
                        //相似则

                    }
                }
            }
            return res;
        
        }
        public void copyPicAndShowTrait(int cellX,int cellY) //已无用
        {
            Bitmap bmpSource = new Bitmap(MapFileName);            
            Bitmap bmpA = new Bitmap(35, 35);
            //int startx = 369, starty = 419;
            //int cellxx = new random().next(9*16);
            //int cellx = cellxx % 16;
            //int cellY = cellxx / 16;
            
            

            for (int x = 0; x < 35; x++)            
                for (int y = 0; y < 35; y++)
                {
                    Color color= bmpSource.GetPixel(oriX+ cellX*35+x,oriY+ cellY*35+y);
                    bmpA.SetPixel(x, y, color);
                }
            int[] traits= calcTrait(cellX, cellY, bmpSource);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < traits.Length; i++)
            {
                sb.Append(traits[i]);
                sb.Append(",");
            }
            tbInfo.Text = sb.ToString();

            pbOneCell.BackgroundImage = bmpA;
            pbOneCell.Refresh();
            Bitmap bmpBack = (Bitmap)pbMain.BackgroundImage; //在主图中刷上所选项
            Graphics g= Graphics.FromImage(bmpBack);
            g.FillRectangle(Brushes.RoyalBlue, oriX + cellX * 35, oriY + cellY * 35, 35, 35);
            pbMain.Refresh();
            lblNowAt.Text = cellX.ToString() + "," + cellY.ToString();

        }
        public int[] calcTraitOldVersion(int cellX, int cellY, Bitmap bmp)
        {
            int[] traits = new int[cellSize];
            int blueCnt = 0;
            bool isButton = false;
            for (int x = 0; x < cellSize; x++)
            {
                traits[x] = 0;
                for (int y = 0; y < cellSize; y++)
                {
                    Color color = bmp.GetPixel(oriX + cellX * cellSize + x, oriY + cellY * cellSize + y);

                    traits[x] += color.G;
                    if (color.B >= 140 && color.B + 15 > color.R + color.G) blueCnt++;
                    if (color.R == 235 && color.G == 228 && color.B == 193) isButton = true; //有黄色时，必定为按钮，必定不为背景
                    // color.R
                }

            }
            if (isButton) return traits;
            else
            {
                traits[0] = -1;
                return traits;
            }
            //暂时用不到
            if (blueCnt >= 35 * 35 / 3) traits[0] = -1;//当有半数以上是蓝色时，标记为背景（背景特征traits[0]=-1）
            return traits;
        }
        public int[] calcTrait(int cellX,int cellY,Bitmap bmp)
        {
            




 int totalRed = 0;
 int totalBlack = 0;
 bool isButton = false;
 int[] traits = new int[35];

 Rectangle rec = new Rectangle(oriX + 35 * cellX, oriY + 35 * cellY, 35, 35);

 BitmapData bmd = bmp.LockBits(new Rectangle(oriX + 35 * cellX, oriY + 35 * cellY,35,35), ImageLockMode.ReadOnly, bmp.PixelFormat); //bmp.LockBits(rec, System.Drawing.Imaging.ImageLockMode.ReadOnly, bmp.PixelFormat);
 // 开始，锁像素
 int PixelSize = 3;//24位

 int pixelSize = (bmd.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
 unsafe
 {
     for (int y = 0; y < bmd.Height; y++)
     {

         byte* row = (byte*)bmd.Scan0 + (y * bmd.Stride);

         for (int x = 0; x < bmd.Width; x++)
         {

             int b = row[x * PixelSize];
             int g = row[x * PixelSize + 1];
             int r = row[x * PixelSize + 2];

             traits[x] += r;
             if (r == 235 && g == 228 && b == 193) isButton = true; //有黄色时，必定为按钮，必定不为背景
         }

     }
 }
 bmp.UnlockBits(bmd);
          

 if (isButton) return traits;
 else
 {
     traits[0] = -1;
     return traits;
 }

 //if (isButton == false) {return new int[]{-1,-1,-1,-1} }

        }

        private void btnRandom_Click(object sender, EventArgs e)
        {
            if (!isArrayGenarated)
            {
                GenerateArray(MapFileName);
                String mapStr = "";
                for (int y = 0; y < 9; y++)
                {
                    for (int x = 0; x < 16; x++)
                    {
                        mapStr += mapArray[x, y] + ",";
                    }
                    mapStr += "\r\n";
                }
                tbInfo.Text = mapStr;
                isArrayGenarated = true;
            }
            List<int[]> foudPairs = FindAllParis();
            String strRes = "";
            for (int i = 0; i < foudPairs.Count; i++)
            {
                strRes += string.Format("{0},{1} {2},{3} \r\n", foudPairs[i][0], foudPairs[i][1], foudPairs[i][2], foudPairs[i][3]);

            }
            tbInfo.Text = strRes;
            //int[] foundPoint= FindOnePair();
            //tbInfo.Text = string.Format("{0},{1} {2},{3}", foundPoint[0], foundPoint[1], foundPoint[2], foundPoint[3]);

            //测试 两点是否相连函数 的片断
            //String[] pList = tbPosition.Text.Split(new char[] { ' ',',' });
            //bool canLink= canTwoPointLink(int.Parse(pList[0]),int.Parse(pList[1]),int.Parse(pList[2]),int.Parse(pList[3]));
            //tbInfo.Text = canLink.ToString();


            //String[] ss = tbPosition.Text.Split(new char[] { ',' });
            //int cellX = int.Parse(ss[0]);
            //int cellY = int.Parse(ss[1]);
            //tbInfo.Text = copareWith(cellX, cellY);

            ////tbInfo.Text = randomCompare();
            //DrawRectants(tbInfo.Text);
            //copyPicAndShowTrait(Int32.Parse(ss[0]), Int32.Parse(ss[1]));
        }
        /// <summary>
        /// 比较特征
        /// </summary>
        /// <param name="source">源</param>
        /// <param name="newComer">新来的</param>
        /// <returns>相似时返回true,否则返回false</returns>
        private bool compareTraits(int[] source,int[] newComer )
        {
            int diffCnt = 0;
            for (int i = 0; i < cellSize; i++)
            {
                if (Math.Abs(source[i] - newComer[i]) > 200)
                {
                    diffCnt++; 
                }
            }
            
            if (diffCnt <= 1) return true;
            return false;

        }
        private void DrawRectants(string selList)
        {
            Bitmap bmpBack = (Bitmap)pbMain.BackgroundImage; //在主图中刷上所选项
            Graphics g = Graphics.FromImage(bmpBack);
            //g.DrawRectangle(Pens.RoyalBlue, oriX + cellX * 35, oriY + cellY * 35, 35, 35);
            
            String[] recList = selList.Split(new String[] { "\r\n" },StringSplitOptions.RemoveEmptyEntries);
            Pen pen = new Pen(Color.RoyalBlue, 5);
            for (int i = 0; i < recList.Length; i++)
            {
                string[] ss = recList[i].Split(new char[] { ',' });
                int x = int.Parse(ss[0]);
                int y = int.Parse(ss[1]);
                
                g.DrawRectangle(pen, oriX + x * 35, oriY + y * 35, 35, 35);
            }
            g.Dispose();
            pbMain.Refresh();
        
        }
        public List<int[]> FindAllParis()
        {
            List<int[]> foundPairs = new List<int[]>();
            int[] res = new int[4];
            for (int x1 = 0; x1 < 16; x1++)
            {
                for (int y1 = 0; y1 < 9; y1++)
                {
                    int sharp1 = mapArray[x1, y1];
                    if (sharp1 == -1) continue;
                    for (int x2 = 0; x2 < 16; x2++)
                    {
                        for (int y2 = 0; y2 < 9; y2++)
                        {
                            if (x2 * 16 + y2 <= x1 * 16 + y1) continue;
                            if (mapArray[x2, y2] == -1) continue;
                            if (mapArray[x2, y2] != sharp1) continue;
                            if (canTwoPointLink(x1, y1, x2, y2)) //两点能连接时
                            {
                                res[0] = x1;
                                res[1] = y1;
                                res[2] = x2;
                                res[3] = y2;
                                foundPairs.Add(new int[] { x1, y1, x2, y2 });
                                //return res;
                            }
                        }
                    }

                }
            }
            return foundPairs;
        }
        public int[] FindOnePair()
        {            
            int[] res = new int[4];
            for (int x1 = 0; x1 < 16; x1++)
            {
                for (int y1 = 0; y1 < 9; y1++)
                {
                    int sharp1 = mapArray[x1, y1];
                    if (sharp1 == -1) continue;
                    for (int x2 = 0; x2 < 16; x2++)
                    {
                        for (int y2 = 0; y2 < 9; y2++)
                        {
                            if (x2 * 16 + y2 <= x1 * 16 + y1) continue;
                            if (mapArray[x2, y2] == -1) continue;
                            if (mapArray[x2, y2] != sharp1) continue;
                            if (x1==LastX1 && x2==LastX2 && y1==LastY1 && y2==LastY2) continue;
                            //if (x1 == LastX2 && y1 == LastY2 && x2 == LastX1 && y2 == LastY1) continue;
                            if (canTwoPointLink(x1, y1, x2, y2)) //两点能连接时
                            {
                                res[0] = x1;
                                res[1] = y1;
                                res[2] = x2;
                                res[3] = y2;

                                LastX1 = x1;
                                LastY1 = y1;
                                LastX2 = x2;
                                LastY2 = y2;
         
                                return res;
                            }
                        }
                    }

                }
            }
            LastX1 = -1; LastX2 = -1; LastY1 = -1; LastY2 = -1;
            return new int[] { -1, -1, -1, -1 };
        }
        /// <summary>
        /// 测试array中 两点是否能连通
        /// </summary>
        /// <param name="x1"></param>
        /// <param name="y1"></param>
        /// <param name="x2"></param>
        /// <param name="y2"></param>
        /// <returns></returns>
        public bool canTwoPointLink(int x1, int y1, int x2, int y2)
        {
            int[] tmpArr = returnXRange(x1, y1);
            int x1L = tmpArr[0];
            int x1R = tmpArr[1];

            tmpArr = returnXRange(x2, y2);
            int x2L = tmpArr[0];
            int x2R = tmpArr[1];

            int ylo = Math.Min(y1, y2);
            int yHi = Math.Max(y1, y2);
            for (int x = x1L; x <= x1R; x++)
            {
                if (x >= x2L && x <= x2R)
                {
                    bool isThisLineOk = true;
                    for (int y = ylo+1; y < yHi; y++) //小心同线的情况
                    {
                        if (mapArray[x, y] != -1)
                        {
                            isThisLineOk = false;
                            break;
                        }

                    }
                    if (isThisLineOk) return true;                    
                    
                }
            }
            //还要考虑两点直接相接的情况,多虑了
            //以上是横竖横的情况

            tmpArr = returnYRange(x1, y1);
            int y1U = tmpArr[0];
            int y1D = tmpArr[1];

            tmpArr = returnYRange(x2, y2);
            int y2U = tmpArr[0];
            int y2D = tmpArr[1];

            int xlo = Math.Min(x1, x2);
            int xHi = Math.Max(x1, x2);
            for (int y = y1U; y <= y1D; y++)
            {
                if (y >= y2U && y <= y2D)
                {
                    bool isThisLineOk = true;
                    for (int x = xlo + 1; x < xHi; x++) //小心同线的情况
                    {
                        if (mapArray[x, y] != -1)
                        {
                            isThisLineOk = false;
                            break;
                        }

                    }
                    if (isThisLineOk) return true;
                }
            }
            //以上是竖横坚的情况
            return false;

        }
        public int[] returnYRange(int x1, int y1)//y轴方向可以连的点
        {
            int newY1D = y1;
            while (true)
            {
                newY1D += 1;
                if (newY1D >= cellCntY || newY1D < 0) break;
                if (mapArray[x1, newY1D] != -1) break;
            }
            newY1D--;
            int newY1U = y1;
            while (true)
            {
                newY1U -= 1;
                if (newY1U >= cellCntY || newY1U < 0) break;
                if (mapArray[x1, newY1U] != -1) break;
            }
            newY1U++;
            return new int[] {newY1U, newY1D };
        }
        public int[] returnXRange(int x1,int y1) //x轴方向可以连的点
        {
            int newX1R = x1;
            while (true)
            {
                newX1R += 1;
                if (newX1R >= cellCntX || newX1R < 0) break;
                if (mapArray[newX1R, y1] != -1) break;
            }
            newX1R--;
            int newX1L = x1;
            while (true)
            {
                newX1L -= 1;
                if (newX1L >= cellCntX || newX1L < 0) break;
                if (mapArray[newX1L, y1] != -1) break;
            }
            newX1L++;
            return new int[] {newX1L,newX1R };
        }
        /// <summary>
        /// 产生图片矩阵
        /// </summary>
        /// <param name="mapFileName"></param>
        public void GenerateArray(String mapFileName)
        {
            Bitmap bmpSource = new Bitmap(mapFileName);
            mapArray = new int[16, 9];
            List<int[]> foundItems = new List<int[]>();

            for (int x = 0; x < 16; x++)
                for (int y = 0; y < 9; y++)
                {
                    int[] newComer= calcTrait(x, y, bmpSource);
                    if (newComer[0] == -1)
                    {
                        mapArray[x, y] = -1;//是背景
                        continue;
                    }
                    bool isFoundTheSame = false;
                    for (int i = 0; i < foundItems.Count; i++)
                    {
                        if (compareTraits(foundItems[i], newComer))
                        {
                            isFoundTheSame = true;
                            mapArray[x, y] = i;
                            break;
                        }
                    }
                    if (isFoundTheSame == false)
                    {
                        foundItems.Add(newComer);
                        mapArray[x, y] = foundItems.Count-1;
                    }
                }
            bmpSource.Dispose();
           
        }
        /// <summary>
        /// 寻找最后一张图，并生成命令文件，删除已处理图像bmp文件
        /// </summary>
        public void FindLatestBmpPic()
        {
            DirectoryInfo dinfo = new DirectoryInfo(workingPath);
            FileInfo[] files= dinfo.GetFiles("*.bmp");
            //Array.Sort(files); 记得排序

            for (int i = files.Length - 1; i >= 0; i--)
            {
                string orderFile= files[i].FullName.Replace(".bmp",".ord");
                if (File.Exists(orderFile))
                {
                    try
                    {
                        files[i].Delete(); //删除已破解的文件
                    }
                    catch (Exception)
                    {


                    }
                    continue;
                }
                
                GenerateArray(files[i].FullName);
                int[]orderArr= FindOnePair();

                FileStream fs = new FileStream(orderFile, FileMode.OpenOrCreate);
                StreamWriter sw = new StreamWriter(fs);
                if (orderArr[0] == -1)
                {
                    sw.WriteLine("-1");
                    sw.WriteLine("-1");
                    sw.WriteLine("-1");
                    sw.WriteLine("-1");
                }
                else
                {
                    sw.WriteLine(orderArr[0].ToString());
                    sw.WriteLine(orderArr[1].ToString());
                    sw.WriteLine(orderArr[2].ToString());
                    sw.WriteLine(orderArr[3].ToString());

                    //sw.WriteLine(string.Format("{0}", orderArr[0] * 35 + oriX + 18));
                    //sw.WriteLine(string.Format("{0}", orderArr[1] * 35 + oriY + 18));
                    //sw.WriteLine(string.Format("{0}", orderArr[2] * 35 + oriX + 18));
                    //sw.WriteLine(string.Format("{0}", orderArr[3] * 35 + oriY + 18));
                }
                sw.Close();

                tbResult.Text = string.Format("{0},{1} - {2},{3}", orderArr[0], orderArr[1], orderArr[2], orderArr[3]);

                try
                {
                    files[i].Delete(); //删除已破解的文件
                }
                catch (Exception )
                {
                  
                    
                }
                FileInfo[] orderfiles = dinfo.GetFiles("*.ord");
                if (orderfiles[0].FullName != orderFile)
                {
                    try
                    {
                        orderfiles[0].Delete();
                    }
                    catch { }       
                }
                break;
            }
            //Flo
            //File file=File.

        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void btnCalculate_Click(object sender, EventArgs e)
        {
            this.Text = "计算中";
            FindLatestBmpPic();
            this.Text = "计算完成";

        }
    }
}